<!--
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-07-16 10:06:40
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-08-23 08:44:18
 * @FilePath: /vue3-uniapp/src/components/ui/FixedBottom/FixedBottom.vue
-->
<script lang="ts" setup>
import { Subject } from 'rxjs';

import { useAfterAuth } from '@/service/hook/useAfterAuth';
import { useKeyboard } from '@/service/app/useKeyboard';

import { useCurrentPageHeightSubject } from './useCurrentPageHeightChange';

const props = withDefaults(
    defineProps<{
        height?: number;
        withKeyboardUp?: boolean;
        bgColor?: string;
    }>(),
    {
        withKeyboardUp: false,
        bgColor: 'transparent'
    }
);
const emits = defineEmits<{
    (event: 'update:height', value: number): void;
}>();
const { withKeyboardUp, bgColor, height } = toRefs(props);

const phHeight = ref(0);
const safeBottom = uni.$uv.sys().safeAreaInsets?.bottom;
const keyboardHeight = ref(safeBottom);

watch(
    () => height.value,
    (newVal) => {
        if (typeof newVal === 'number') {
            phHeight.value = newVal;
        }
    }
);

const instance = getCurrentInstance();

const subject = new Subject<'mounted' | 'auth' | 'keyboard'>();
const source$ = subject.pipe(debounceTime(100));
const subscription = source$.subscribe({
    next: () => {
        resetHeight();
    }
});

const { notifyHeighChange } = useCurrentPageHeightSubject();

const resetHeight = async () => {
    const query = uni.createSelectorQuery().in(instance);
    query
        .select('.fixed-bottom-container')
        .boundingClientRect((data) => {
            const height = Array.isArray(data) ? data[0].height : data.height;
            if (height === undefined) {
                throw new Error('[FixedBottom]获取不到内部组件高度');
            }
            phHeight.value = height;
            emits('update:height', height);
            notifyHeighChange(height);
        })
        .exec();
};

const { onKeyboardHeightChange } = useKeyboard();
onKeyboardHeightChange((keyboardHeight) => {
    if (withKeyboardUp.value) {
        keyboardHeight = keyboardHeight;
        nextTick(() => {
            subject.next('keyboard');
        });
    }
});

useAfterAuth(() => {
    subject.next('auth');
    uni.$uv.debounce(resetHeight, 500);
});
onMounted(() => {
    subject.next('mounted');
    uni.$uv.debounce(resetHeight, 500);
});
onBeforeUnmount(() => {
    subscription.unsubscribe();
});
</script>

<template>
    <view class="fixed-top-wrap">
        <view
            class="fixed-bottom-container"
            :style="{ backgroundColor: bgColor }"
        >
            <slot></slot>
            <view :style="{ minHeight: keyboardHeight + 'px' }" />
        </view>
        <view class="placeholder" :style="{ height: phHeight + 'px' }" />
    </view>
</template>

<style lang="scss" scoped>
.fixed-bottom-container {
    width: 100%;
    position: fixed;
    left: 0;
    bottom: 0;
    z-index: 10;
}
</style>
